<template>
    <n-form
        ref="formRef"
        :model="formState"
        label-placement="left"
        label-align="right"
        label-width="5rem"
    >
        <n-grid :cols="cols" responsive="screen">
            <n-gi v-for="item in items" :key="item.field">
                <n-form-item
                    :label="item.label"
                    :path="<string>item.field"
                    :rule="item.rule"
                >
                    <slot
                        v-if="$slots[<string>item.field]"
                        :name="item.field"
                        :modelValue="formState[<string>item.field]"
                        :updateModelValue="
                            (newValue: string | number) =>
                                (formState[<string>item.field] = newValue)
                        "
                        :props="item.props"
                    />

                    <!-- 单行文本 & 多行文本 -->
                    <n-input
                        v-if="item.component === 'Input'"
                        clearable
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />

                    <!-- 数字 -->
                    <n-input-number
                        v-if="item.component === 'InputNumber'"
                        clearable
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />

                    <!-- 下拉 -->
                    <n-select
                        v-if="item.component === 'Select'"
                        clearable
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />

                    <!-- 单选 -->
                    <RadioGroup
                        v-if="item.component === 'RadioGroup'"
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />

                    <!-- 复选 -->
                    <n-checkbox
                        v-if="item.component === 'Checkbox'"
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />
                    <CheckboxGroup
                        v-if="item.component === 'CheckboxGroup'"
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />

                    <!-- 日期选择 -->
                    <n-date-picker
                        v-if="item.component === 'DatePicker'"
                        clearable
                        v-model:value="formState[<string>item.field]"
                        v-bind="item.props"
                    />
                </n-form-item>
            </n-gi>

            <n-gi suffix>
                <slot name="tool" v-if="$slots.tool"></slot>
                <n-form-item label=" " v-else>
                    <n-space>
                        <n-button @click="onReset" secondary :disabled="loading"
                            >清空</n-button
                        >
                        <n-button
                            @click="onSubmit"
                            type="primary"
                            secondary
                            :loading="loading"
                            >提交</n-button
                        >
                    </n-space>
                </n-form-item>
            </n-gi>
        </n-grid>
    </n-form>
</template>

<script setup lang="ts">
import { computed, PropType, ref } from 'vue'
import { FormItemsConfig, FormStateType } from '../types'
import { FormInst } from 'naive-ui'
import RadioGroup from '../components/RadioGroup.vue'
import CheckboxGroup from '../components/CheckboxGroup.vue'

const emits = defineEmits(['update:value', 'update:loading', 'reset', 'submit'])

type ResponsiveDescription = string // 1 m:2 xl:4 2xl:7
const props = defineProps({
    items: {
        type: Object as PropType<FormItemsConfig<any>>,
        required: true
    },
    value: {
        type: Object as PropType<FormStateType>,
        required: true
    },
    loading: {
        type: Boolean,
        default: () => false
    },
    cols: {
        type: [Number, String] as PropType<number | ResponsiveDescription>,
        default: () => '1 m:2 l:3 xl:4 2xl:7'
    }
})

const formRef = ref<FormInst>()
const formState = computed<FormStateType>({
    get: () => props.value,
    set: (val) => emits('update:value', val)
})

function onSubmit() {
    formRef.value
        ?.validate()
        .then(() => {
            emits('submit')
        })
        .catch((_) => {
            // 占位
        })
}

function onReset() {
    formRef.value?.restoreValidation()

    for (const key in formState.value) {
        if (Object.prototype.hasOwnProperty.call(formState.value, key)) {
            const element = formState.value[key]
            if (Array.isArray(element)) {
                formState.value[key].length = 0
            } else {
                formState.value[key] = null
            }
        }
    }

    emits('reset')
}
</script>
